package pers.cz.postgirl.core;

import javassist.CtClass;
import pers.cz.postgirl.core.common.ParamFilter;

/**
 * @program: postgirl-client
 * @description: 间谍构造器
 * @author: Cheng Zhi
 * @create: 2023-12-20 10:34
 **/
public class SpyBuilder {

    private String clzName;

    private String methodName;

    private CtClass[] parameterTypes;

    SpyBuilder(String clzName, String methodName, CtClass[] parameterTypes) {
        this.clzName = clzName;
        this.methodName = methodName;
        this.parameterTypes = parameterTypes;
    }

    /**
     * 返回的是一个完整的组织好参数的SPY字符串
     * @return
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("try {\n");
        sb.append("          pers.cz.postgirl.core.Spy spy = new pers.cz.postgirl.core.Spy();\n");
        sb.append("          spy.setStartTime(System.currentTimeMillis());\n");
        sb.append("          spy.setMethodName(");
        sb.append(getString(this.methodName) + ");\n");
        sb.append("          spy.setClzName(");
        sb.append(getString(this.clzName) + ");\n");
        sb.append(createDumpParams(parameterTypes));
        sb.append("          spy.setDataType(pers.cz.postgirl.core.Spy.DataType.INPUT);\n");
        sb.append("        } catch (Exception e) {\n");
        sb.append("            e.printStackTrace();\n");
        sb.append( "        }");
        return sb.toString();
    }

    /**
     * 创建出参的插码
     * @param returnType    返回值类型
     * @return  插码结果
     */
    private String createDumpReturnValue(String returnType) {
        StringBuilder sb = new StringBuilder();
        if ("void".equals(returnType)) {
            sb.append("spy.putReturnValue(");
            sb.append(getString(returnType));
            sb.append(",").append(getString("")).append(");\n");
        } else {
            sb.append("spy.putReturnValue(")
                    .append(getString(returnType))
                    .append(",$_);\n");
        }
        return sb.toString();
    }

    private String createDumpParams(CtClass[] parameterTypes) {
        StringBuilder sb = new StringBuilder();
        if (parameterTypes != null && parameterTypes.length > 0) {
            for (int i = 0; i < parameterTypes.length; i++) {

                if (!ParamFilter.isNeedfilterParam(parameterTypes[i].getName())) {
                    sb.append("          spy.addParam(\"");
                    sb.append(parameterTypes[i].getName());
                    sb.append("\",$");
                    sb.append(i + 1);
                    sb.append(");\n");
                }
            }
        }
        // mybatis比较特殊，为了增加对比时的准确性，新增Mapper.xml中的id 和 type ，<select id="selectByExample" resultMap="BaseResultMap" parameterType="pers.cz.model.AutoCollectMethodParamsExample"></select>
        sb.append("            spy.addParam(this.command.getType());\n");
        sb.append("            spy.addParam(this.command.getName());\n");
        return sb.toString();
    }

    private String transReturn(String returnType) {
        if("int".equals(returnType)){
            return "              return Integer.parseInt(myResult$.getReturnValue().toString());\n";
        }else if("long".equals(returnType)){
            return "              return Long.parseLong(myResult$.getReturnValue().toString());\n";
        }else if("float".equals(returnType)){
            return "              return Float.parseFloat(myResult$.getReturnValue().toString());\n";
        }else if("double".equals(returnType)){
            return "              return Double.parseDouble(myResult$.getReturnValue().toString());\n";
        }else if("byte".equals(returnType)){
            return "              return Byte.parseByte(myResult$.getReturnValue().toString());\n";
        }else if("short".equals(returnType)){
            return "              return Short.parseShort(myResult$.getReturnValue().toString());\n";
        }else if("char".equals(returnType)){
            return "              return myResult$.getReturnValue().toString().charAt(0);\n";
        }else if("boolean".equals(returnType)){
            return "              return Boolean.parseBoolean(myResult$.getReturnValue().toString());\n";
        }else if("void".equals(returnType)) {
            return "              return;\n";
        } else if("java.lang.Object".equals(returnType)) {
            // return  "             return pers.cz.postgirl.util.JsonUtils.spyToObj(myResult$);\n";
            return  "             return myResult$.getReturnValue();\n";
        } else{
            return "              return ("+returnType+")myResult$.getReturnValue();\n"; // 如果使用fastJSON直接强转可能会报错
        }
    }

    private String getString(String data) {
        return "\"" + data + "\"";
    }

    public static class InnerBuilder {

        private String clzName;

        private String methodName;

        private CtClass[] parameterTypes;

        public InnerBuilder clzName(String clzName) {
            this.clzName = clzName;
            return this;
        }

        public InnerBuilder methodName(String methodName) {
            this.methodName = methodName;
            return this;
        }

        public InnerBuilder paramters(CtClass[] parameterTypes) {
            this.parameterTypes = parameterTypes;
            return this;
        }

        public SpyBuilder build() {
            return new SpyBuilder(clzName, methodName, parameterTypes);
        }
    }


}
